package org.swingplus.core.util;

import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swingplus.core.annotation.Autowired;
import org.swingplus.core.annotation.Internal;
import org.swingplus.core.annotation.Style;
import org.swingplus.core.annotation.layout.Layout;
import org.swingplus.core.annotation.widget.Frame;
import org.swingplus.core.annotation.widget.Widget;
import org.swingplus.core.bean.MetaData;
import org.swingplus.core.bean.MetaDataType;
import org.swingplus.core.constant.bean.ScopeConstant;
import org.swingplus.core.context.ApplicationContext;
import org.swingplus.core.exception.BeanCreateException;
import org.swingplus.core.factory.AbstractAutowireBeanFactory;
import org.swingplus.core.factory.WidgetFactroy;
import org.swingplus.core.scanner.OrderScan;
import org.swingplus.core.scanner.WidgetScan;
import org.swingplus.core.utils.ClassFileInfoParse;
import org.swingplus.core.utils.ClassFileInfoParseUtil;
import org.swingplus.core.utils.StringUtil;
import org.swingplus.core.widget.WidgetActvity;

import javax.swing.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

//import

public final class AnnoManageUtil {

    private static final Logger logger = LoggerFactory.getLogger(AnnoManageUtil.class);


    /**
     * 获取指定文件下面的RequestMapping方法保存在mapp中
     *
     * @param
     * @return
     */
//    public static Map<String, ExecutorBean> getFrameClass(String packageName) {
//        Reflections reflections = new Reflections(packageName);
//        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(Frame.class);
//
//        // 存放url和ExecutorBean的对应关系
//        Map<String, ExecutorBean> mapp = new HashMap<String, ExecutorBean>();
//        for (Class classes : classesList) {
//            //得到该类下面的所有方法
//            Method[] methods = classes.getDeclaredMethods();
//
//            for (Method method : methods) {
//                //得到该类下面的RequestMapping注解
//                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
//                if (null != requestMapping) {
//                    ExecutorBean executorBean = new ExecutorBean();
//                    try {
//                        executorBean.setObject(classes.newInstance());
//                    } catch (InstantiationException e) {
//                        e.printStackTrace();
//                    } catch (IllegalAccessException e) {
//                        e.printStackTrace();
//                    }
//                    executorBean.setMethod(method);
//                    mapp.put(requestMapping.value(), executorBean);
//
//                }
//            }
//        }
//        return mapp;
//    }


//	public static Annotation[] annotationsType(Class clazz) {
//		Annotation[] annotationsByType = clazz.getDeclaredAnnotations();
//        return annotationsByType;
//
//	}


    /**
     * 根据注解创建bean
     *
     * @param clazz
     */
    public static List<Object> createBeanByAnnotationsType(String packageName, Class clazz) {
        List<Object> instance = new ArrayList<>();
        Annotation[] annotationsByType = clazz.getDeclaredAnnotations();
        Reflections reflections = new Reflections(packageName, clazz);
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(clazz);
        logger.info("discover Annotation {} size: {} classpath: {}", clazz, classesList.size());
        for (Class<?> class1 : classesList) {
            Annotation annotation = class1.getAnnotation(clazz);
            String value = "";
            String[] alias = null;
//			if(annotation.annotationType()==Widget.class){
//				value = ((Widget) annotation).value();
//			}else if(annotation.annotationType()==Style.class){
//				value = ((Style) annotation).value();
//			}else if(annotation.annotationType()==Layout.class){
//				value = ((Layout) annotation).value();
//			}
            if (clazz == Widget.class) {
                value = ((Widget) annotation).value();
                alias = ((Widget) annotation).alias();
            } else if (clazz == Style.class) {
                value = ((Style) annotation).value();
                alias = ((Style) annotation).alias();
            } else if (clazz == Layout.class) {
                value = ((Layout) annotation).value();
                alias = ((Layout) annotation).alias();
            } else {
                logger.error("扫描没有匹配的类型");
            }


            Object obj = WidgetFactroy.create(class1.getName());
            if (("").equals(value)) {
                // 默认类名首字母小写 ，key
                ApplicationContext.setBean(StringUtil.lowerFirst(class1.getSimpleName()), obj);
            } else {
                // 使用注解声明的key作为变量
                ApplicationContext.setBean(value, obj);
            }
            if (null != alias) {
                logger.info("别名不为空:{}", alias[0]);
//			    if(alias.length==1&&!alias[0].equals("")){
//                    ApplicationContext.setBean(alias[0], obj);
//                }else{
                for (String str : alias) {
                    if (("").equals(str)) {
                        continue;
                    } else {
                        logger.info("别名不为空:{}", str);
                        // 使用注解声明的key作为变量
                        ApplicationContext.setBean(str, obj);
                    }
                }
//                }
            }
            instance.add(obj);
        }
        if (logger.isDebugEnabled()) {
            logger.info("{} annotation create {} bean", clazz.getSimpleName(), instance.size());
        }
        return instance;
    }

    public static Annotation[] annotationsType(Class clazz) {
        Annotation[] annotationsByType = clazz.getDeclaredAnnotations();
        Reflections reflections = new Reflections("", clazz);
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(clazz);
        for (Class<?> class1 : classesList) {
            Annotation annotation = class1.getAnnotation(clazz);
            String value = ((Widget) annotation).value();
            String[] alias = ((Widget) annotation).alias();

            Object ff = WidgetFactroy.create(class1.getName());

            if (("").equals(value)) {
                // 默认类名首字母小写 ，key
                ApplicationContext.setBean(StringUtil.lowerFirst(class1.getSimpleName()), ff);
            } else {
                // 使用注解声明的key作为变量
                ApplicationContext.setBean(value, ff);
            }
            if (null != alias) {
                if (alias.length == 1 && !alias[0].equals("")) {
                    ApplicationContext.setBean(StringUtil.lowerFirst(alias[0]), ff);
                } else {
                    for (String str : alias) {
                        if (("").equals(str)) {
                            // 默认类名首字母小写 ，key
                            ApplicationContext.setBean(StringUtil.lowerFirst(class1.getSimpleName()), ff);
                        } else {
                            // 使用注解声明的key作为变量
                            ApplicationContext.setBean(str, ff);
                        }
                    }
                }
            }


//           if(null==value){
//               ApplicationContext.setBean(StringUtil.lowerFirst(class1.getSimpleName()), ff);
//           }else{
//               for (String str:
//                       value) {
//                   if (("").equals(str)) {
//                       // 默认类名首字母小写 ，key
//                       ApplicationContext.setBean(StringUtil.lowerFirst(class1.getSimpleName()), ff);
//                   } else {
//                       // 使用注解声明的key作为变量
//                       ApplicationContext.setBean(str, ff);
//                   }
//               }
//           }
        }
        return annotationsByType;

    }


    /**
     * 实例 中 使用注解 的 属性 集合
     *
     * @param obj   实例
     * @param clazz 注解
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Map<Field, Annotation[]> fieldByAnnotationsType(Object obj, Class clazz) {
        Map<Field, Annotation[]> map = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            Annotation[] annotations = field.getDeclaredAnnotations();
            if (annotations != null && annotations.length != 0) {
                for (int j = 0; j < annotations.length; j++) {
                    String simpleName = annotations[j].annotationType().getSimpleName();
                    if (simpleName.equals(clazz.getSimpleName())) {
                        map.put(field, annotations);
                    }
                }

//				if(annotation instanceof CustomAnnotation){
//		            CustomAnnotation customAnnotation = (CustomAnnotation) annotation;
//		            System.out.println("name: " + customAnnotation.name());
//		            System.out.println("value: " + customAnnotation.value());
//		         }

            }
        }
        return map;

    }

    @SuppressWarnings("unchecked")
    public static Map<Field, Annotation[]> fieldAnnotationsType(Object obj) {
        Map<Field, Annotation[]> map = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            map.put(field, field.getDeclaredAnnotations());
//
        }
        return map;

    }

    public static Map<String, String> getFrameType(String packageName) {
        Reflections reflections = new Reflections(packageName);
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(Frame.class);

        // 存放url和ExecutorBean的对应关系
        Map<String, String> mapp = new HashMap<String, String>();
        for (Class<?> classes : classesList) {
            System.out.println(classes.getName());
            Object ff = WidgetFactroy.create(classes.getName());
            Method setVisibleMethod = null;
            try {
                setVisibleMethod = ff.getClass().getMethod("setVisible", new Class[]{boolean.class});
            } catch (NoSuchMethodException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            } catch (SecurityException e2) {
                // TODO Auto-generated catch block
                e2.printStackTrace();
            }

            //得到该类下面的所有方法
            @SuppressWarnings("unused")
            Method[] methods = classes.getDeclaredMethods();
            Field[] fields = classes.getDeclaredFields();
            for (Field field : fields) {
                if ("controlPanel".equals(field.getName())) {
                    field.setAccessible(true);
                    try {
                        Object obj = field.get(ff);
                        if (null == field.get(ff)) {
                            obj = WidgetFactroy.create(field.getType().toString().split(" ")[1]);
//		            		JPanel jPanel=(JPanel)ssdd;
                        }
                        WidgetActvity.onCreate(obj, field);
                        System.out.println("Object create:" + obj);
                        try {
                            field.set(ff, obj);
                        } catch (IllegalArgumentException | IllegalAccessException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        field.setAccessible(false);
                        //得到该类下面的RequestMapping注解
                        System.out.println("fieldName:" + field.getName());
                        System.out.println("fieldType:" + field.getType());
                        System.out.println("fieldClass:" + field.getClass());
                        System.out.println("fieldModifier:" + field.getModifiers());
                        try {
                            setVisibleMethod.invoke(ff, true);
                        } catch (InvocationTargetException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    } catch (IllegalArgumentException | IllegalAccessException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }


                }
//            	field.
                Annotation[] annotations = field.getAnnotations();
                for (Annotation annotation : annotations) {
                    System.out.println("annotationType:" + annotation.annotationType().getName());
//                	 System.out.println(annotation.getName());
                }
            }
        }
        return mapp;
    }


    /**
     * 获得获取扫描注解的类 元数据信息 类名 类名上的注解 字段 字段上注解
     *
     * @param packageName
     * @param clazz
     * @return
     */
    public static MetaData getAnnotationType(String packageName, Class clazz) {
        MetaDataType metaDataType = null;
        List<MetaDataType> metaDataTypeList = new ArrayList<>();
        MetaData meteData = new MetaData();
        List<Object> instances = new ArrayList<>();

        Reflections reflections = new Reflections(packageName);
        @SuppressWarnings("unchecked")
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(clazz);
        // 存放url和ExecutorBean的对应关系
        for (Class<?> classes : classesList) {
            metaDataType = new MetaDataType();
            Map<Field, Annotation[]> map = new HashMap<>();
            String simpleName = clazz.getSimpleName();
            String name = clazz.getName();
            Annotation[] annotationsType = classes.getDeclaredAnnotations();
            meteData.setAnnotationsType(annotationsType);
            metaDataType.setAnnotationsType(annotationsType);
            logger.info("discover Type Annotation:[type:{},typeClasspath:{},typeAnnotationSizes:{}]", classes.getSimpleName(), classes.getTypeName(), annotationsType.length);
            System.out.println("discover Annotation: " + simpleName + " size:" + classesList.size() + " classpath: " + name);
            logger.info("discover Annotation {} size: {} classpath: {}", clazz, classesList.size(), name);
            Object obj = WidgetFactroy.create(classes.getName());
            logger.error("SimpleName:{}", StringUtil.lowerFirst(classes.getSimpleName()));
            ApplicationContext.setBean(StringUtil.lowerFirst(classes.getSimpleName()), obj);
            metaDataType.setInstance(obj);
            instances.add(obj);
            Field[] fields = classes.getDeclaredFields();
            metaDataType.setFields(fields);
            for (Field field : fields) {
                //exists Annotation choject
                Annotation autowired = field.getAnnotation(Autowired.class);
                if (null != autowired) {
                    continue;
                }
                Annotation[] annotations = field.getAnnotations();
                if (null != annotations && annotations.length != 0) {
                    for (Annotation annotation : annotations) {
                        System.out.println("discover " + field.getName() + " annotationType:" + annotation.annotationType().getName());
//                	 System.out.println(annotation.getName());
                    }

                    try {
                        field.setAccessible(true);
                        Object fieldObj = field.get(obj);
                        String fieldType = field.getType().getName();
                        if (null == fieldObj) {
                            fieldObj = WidgetFactroy.create(field.getType().getName());
//		            		JPanel jPanel=(JPanel)ssdd;
                        }
                        WidgetActvity.onCreate(fieldObj, field);
//						System.out.println("Object create:"+fieldObj);

                        try {
                            System.out.println("Object create:" + fieldObj);
                            field.setAccessible(true);
                            field.set(obj, fieldObj);
                        } catch (IllegalArgumentException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        WidgetActvity.onCreate(fieldObj, field);
                        field.setAccessible(false);
                        //得到该类下面的RequestMapping注解
                        System.out.println("field[Name:" + field.getName() + " Type:" + fieldType + " Modifier:" + field.getModifiers());
                        logger.info("field[Name:{} Type:{} Modifier:{}" + field.getName(), fieldType, field.getModifiers());
                        map.put(field, annotations);
                    } catch (IllegalArgumentException | IllegalAccessException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
//			    meteData.setMap(map);
            }
            metaDataType.setMap(map);
            metaDataTypeList.add(metaDataType);
        }
        meteData.setInstances(instances);
        meteData.setInstanceType(metaDataTypeList);
        return meteData;
    }


    @SuppressWarnings("rawtypes")
    public static Map<String, Object> createByAnnotationType(String packageName, Class clazz) {
        Reflections reflections = new Reflections(packageName);
        @SuppressWarnings("unchecked")
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(clazz);
        // 存放url和ExecutorBean的对应关系
        Map<String, Object> objMap = new HashMap<>();

        for (Class<?> classes : classesList) {
//        	String simpleName=clazz.getSimpleName();

            String classesSimpleName = classes.getSimpleName();
            String classesName = classes.getName();
            String simpleName = clazz.getSimpleName();

            String name = clazz.getName();
            System.out.println("discover Annotation: " + simpleName + " size:" + classesList.size() + " classpath: " + name);
            logger.info("discover Annotation {} size: {} classpath: {}", clazz, classesList.size(), name);
            Annotation[] annotationsClass = classes.getAnnotations();
            System.out.println("discover " + classesSimpleName + " annotations size: " + annotationsClass.length);
            for (Annotation annotation : annotationsClass) {
                System.out.print("       " + annotation.annotationType().getSimpleName() + " ");
//        		annotation
            }
            if (annotationsClass.length != 0) {
                System.out.println();
            }
//        	Scope scope = classes.getAnnotation(Scope.class);
            Object obj = null;
//        	if(scope!=null) {
//        		obj=WidgetFactroy.create(classesName,classesSimpleName,scope.value());
//        	}else {
            obj = WidgetFactroy.create(classesName, classesSimpleName, ScopeConstant.singleton);
//        	}
            Field[] fields = classes.getDeclaredFields();
            for (Field field : fields) {
                //exists Annotation choject
//				field.
                Annotation[] annotations = field.getAnnotations();
                if (null != annotations && annotations.length != 0) {
                    for (Annotation annotation : annotations) {
                        System.out.println("discover " + field.getName() + " annotationType:" + annotation.annotationType().getName());
//                	 System.out.println(annotation.getName());
                    }
                }
            }
            objMap.put(StringUtil.lowerFirst(classesSimpleName), obj);

        }

        return objMap;
    }

    /**
     * 扫描类中成员变量上Internal注解中注入容器变量(该组件设置为与父容器通讯的组件)
     *
     * @param objs
     * @return
     */
    public static MetaData internal(List<Object> objs) {
        //TODO 元数据目前没有使用
        MetaData meteData = new MetaData();
        for (Object obj : objs) {
            internal(obj, obj);
        }
        return meteData;
    }

    /**
     * 扫描类中成员变量上Internal注解中注入容器变量
     *
     * @param obj
     */
    public static void internal(Object obj, Object rootObj) {
        if(null==obj){
            throw new NullPointerException("obj is null 扫描类中成员变量上Internal注解中注入容器变量");
        }

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            Internal internal = field.getAnnotation(Internal.class);
            if (null != internal) {
                Object fieldObj = null;
                try {
                    field.setAccessible(true);
                    fieldObj = field.get(obj);
                    if (null == fieldObj) {
                        Class[] clazzs = internal.parameterTypes();
                        //TODO 如果初始化是构造参数的，怎么通过Antowired引用，目前如果是有内部通讯组件，如果有Autowired也不像容器中找bean
                        //TODO 目前已经脱离Autowired,单独使用并处理
                        if (internal.isCommunication()) {
                            Constructor constructor = field.getType().getConstructor(clazzs[0]);
                            //TODO 注解中参数parameters多个参数时会有问题
                            if (internal.model()) {
                                fieldObj = constructor.newInstance((JPanel) obj);
                                WidgetScan.widgetScan(fieldObj);
                                AnnoManageUtil.autowired(fieldObj);


                                internal(fieldObj, rootObj);

                                OrderScan.orderScan(fieldObj);
                            } else {
                                fieldObj = constructor.newInstance((JPanel) rootObj);
                                WidgetScan.widgetScan(fieldObj);
                                AnnoManageUtil.autowired(fieldObj);


                                internal(fieldObj, rootObj);

                                OrderScan.orderScan(fieldObj);
                            }

                        }
                    }
                    if (null == fieldObj) {
                        //容器中没找到抛出异常
                        throw new BeanCreateException("");
                    }
                    field.set(obj, fieldObj);
                } catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException e) {
                    logger.info("{},{}", field.getName(), field.getType());
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                field.setAccessible(false);
            }

        }
        return;
    }

    /**
     * 扫描类中成员变量上Internal注解中注入容器变量
     *
     * @param cls
     */
    public static void internal(Class cls, Object obj) {

        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            Internal internal = field.getAnnotation(Internal.class);
            if (null != internal) {
                Object fieldObj = null;
                try {
                    field.setAccessible(true);
                    Class[] clazzs = internal.parameterTypes();
                    if (internal.isCommunication()) {
                        internal(field.getType(), obj);
                    } else {
                        Constructor constructor = field.getType().getConstructor(clazzs[0]);
                        //TODO 注解中参数parameters多个参数时会有问题
                        fieldObj = constructor.newInstance((JPanel) obj);
                    }
                    if (null == fieldObj) {
                        //容器中没找到抛出异常
                        throw new BeanCreateException("");
                    }
                    field.set(obj, fieldObj);
                } catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException e) {
                    logger.info("{},{}", field.getName(), field.getType());
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
                field.setAccessible(false);
            }
        }
        return;
    }


    /**
     * 扫描类中成员变量上Autowired注解中注入容器变量
     *
     * @param objs
     * @return
     */
    public static MetaData autowired(List<Object> objs) {
        //TODO 元数据目前没有使用
        MetaData meteData = new MetaData();
        for (Object obj : objs) {
            autowired(obj);
        }
        return meteData;
    }

    /**
     * 扫描类中成员变量上Autowired注解中注入容器变量
     *
     * @param obj
     */
    public static void autowired(Object obj) {

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            //exists Annotation choject
            Annotation autowired = field.getAnnotation(Autowired.class);
            if (null != autowired) {
                Object fieldObj = ApplicationContext.getBean(field.getName());
                if (null == fieldObj) {
                    //容器中没找到抛出异常
                    logger.info("容器中没找到{}", field.getName());
                    System.out.println("容器中没找到" + field.getName());

//                    obj.getClass().getSimpleName();
                   // AbstractAutowireBeanFactory.getBean(field.getName(),new ClassFileInfoParse(field.getType()).getDefinitionMetadata());


                    throw new BeanCreateException("");
                    //TODO 容器中没有是否自主创建
                    //fieldObj=WidgetFactroy.create(field.getType().getName());
                }
                try {
                    field.setAccessible(true);
                    //TODO 在这里是否设置部件属性
//						WidgetActvity.onCreate(fieldObj,field);
                    field.set(obj, fieldObj);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                field.setAccessible(false);
            }
        }
        return;
    }

    /**
     * 构造方法是否存在注入
     * @param clazz
     * @return
     */
    public static boolean existAutowiredConstructors(Field[] fields){
         boolean result=false;
        for (Field field:fields) {
        	if(existAutowiredConstructors(field.getType())) {
        		result=true;
        		break;
        	};
        }
        return result;
    }

    /**
     * 构造方法是否存在注入
     * @param clazz
     * @return
     */
    public static Constructor[] autowiredConstructors(Field[] fields){
    	List<Constructor> constructorList=new ArrayList<>();
    	for (Field field : fields) {
    		Constructor[] constructor =autowiredConstructors(field.getType());
    		if(null!=constructor&&null!=constructor[0]) {
    			constructorList.add(constructor[0]);
    		}
		}
    	if(constructorList.size()>0) {
    		Constructor[] constructors=new Constructor[constructorList.size()];
    		constructors=constructorList.toArray(constructors);
    		return constructors;
    	}
    	return null;
    }



    /**
     * 构造方法是否存在注入
     * @param clazz
     * @return
     */
    public static boolean existAutowiredConstructors(Class clazz){
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor:constructors) {
            Autowired autowired=(Autowired)constructor.getAnnotation(Autowired.class);
            if(autowired!=null){
                return true;
            }
        }
        return false;
    }

    /**
     * 构造方法是否存在注入
     * @param clazz
     * @return
     */
    public static Constructor[] autowiredConstructors(Class clazz){
        List<Constructor> list=new ArrayList<>();
        Constructor[] result = null;
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor:constructors) {
            Autowired autowired=(Autowired)constructor.getAnnotation(Autowired.class);
            if(autowired!=null){
                list.add(constructor);
            }
        }
        int size=list.size();
        if(size>0){
            result=new Constructor[size];
            return list.toArray(result);
        }
        return null;
    }




    /**
     *   扫描注解
     *
     * @param clazz
     */
    public static Set<Class<?>> getTypesAnnotatedWith(String packageName, Class clazz) {
        @SuppressWarnings("unused")
		Annotation[] annotationsByType = clazz.getDeclaredAnnotations();
        Reflections reflections = new Reflections(packageName, clazz);
        @SuppressWarnings("unchecked")
		Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(clazz);
        logger.info("discover Annotation {} size: {} classpath: {}", clazz, classesList.size());
        return classesList;
    }


}